import { createSketion, SketionHttp } from 'sketion-http';
import { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
import { Message, Modal } from '@arco-design/web-vue';
import { clearToken } from '@/utils/auth';
import initAxios from './axios';
import CachePool from './cache';
import { MyRequest, MyResponse } from './net';
import { SendFun } from './send';
import NetError from './error';

let myAxios: AxiosInstance;

let show401Modal = false;

const sendRequestPrivate: SendFun = (request: MyRequest) => {
  return sendRequestWithRes(request);
};

export function initHttp() {
  // console.log('==initHttp==');

  myAxios = initAxios();

  const cache = CachePool.getInstance(sendRequestPrivate);

  return createSketion({
    getDataFromCache: (req: MyRequest) => {
      const { needCache = false } = req;
      if (!needCache) {
        return null;
      }

      return cache.getCache(req);
    },
    beforeRequest: (config) => {
      const { loadingText = '加载中', showLoading = false } = config || {};
      if (showLoading) {
        Message.loading(loadingText);
      }
    },
    afterRequest: (response, request) => {
      const { showLoading = false } = request || {};
      if (showLoading) {
        Message.clear();
      }

      const { showError = true, showWarn = true, successText } = request || {};

      if (!response.success) {
        if (response.code === 401) {
          if (!show401Modal) {
            show401Modal = true;
            Modal.error({
              title: '登录失效',
              content: '当前账号登录失效，请重新登录',
              okText: '重新登录',
              escToClose: false,
              closable: false,
              maskClosable: false,
              alignCenter: true,
              modalStyle: {
                textAlign: 'center',
              },
              async onOk() {
                clearToken();
                // router.replace({
                //   name: 'login',
                // });
                window.location.reload();
              },
              onClose() {
                show401Modal = false;
              },
            });
          }

          return response;
        }
        if (response.isLocalError) {
          if (showError) {
            // const message = response.msg;
            Message.error(response.msg);
          }
        } else if (showWarn) {
          const { msg = '出现了点问题' } = response;
          // 401代表登陆过期时，如果此时token为空的话，说明前面已经提示过用户登陆过期了，不需要再次提示
          Message.warning(msg);
        }
      } else if (successText) {
        Message.success(successText);
      }

      return response;
    },
    sendRequest(request) {
      // console.log('req', request);
      return myAxios.request(request);
    },
    parseRes(res: any) {
      // console.log('parseRes', res);
      const axiosRes = res as AxiosResponse;
      if (axiosRes.status === 200) {
        // 下载文件时特殊处理
        if (
          axiosRes.request.responseType === 'blob' &&
          axiosRes.data instanceof Blob
        ) {
          return Promise.resolve(
            new MyResponse({
              code: 0,
              data: axiosRes.data,
              msg: 'success',
              $originalData: axiosRes,
            })
          );
        }
        const resData = axiosRes.data as any;
        if (resData) {
          return Promise.resolve(
            new MyResponse({
              code: resData.code,
              data: resData.data,
              msg: resData.msg,
              $originalData: axiosRes,
            })
          );
        }
        return Promise.resolve(
          new MyResponse({
            code: -1,
            data: null,
            msg: 'resData is null',
            $originalData: axiosRes,
          })
        );
      }
      return new MyResponse({
        code: axiosRes.status,
        data: null,
        msg: `未知错误(${axiosRes.status})，请检查网络或联系管理员！`,
        $originalData: axiosRes,
      });
    },
    parseError(error: AxiosError) {
      // 500, error.message, null, error
      //   5000 相当于本地错误，如断网请求超时
      return new MyResponse({
        code: 5000,
        data: null,
        msg: error.message,
        $originalData: error,
      });
    },
  });
}

export function setHeader(key: string, value: string) {
  myAxios.defaults.headers.common[key] = value;
}

export function removeHeader(key: string) {
  delete myAxios.defaults.headers.common[key];
}

export function getAxiosInstance() {
  return myAxios;
}

const sketionUtil: SketionHttp<MyRequest, MyResponse> = initHttp();

export const sendRequest = <T = any>(request: MyRequest): Promise<T> => {
  return sketionUtil.sendRequest(request).then((res) => {
    if (res.success) {
      return res.data;
    }
    return Promise.reject(new NetError(res.msg, res.code));
  });
};
export function sendRequestWithRes<T = any>(
  request: MyRequest
): Promise<MyResponse<T>> {
  return sketionUtil.sendRequest(request);
}
